package qf.common.logback.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.UUID;

/**
 * 生成唯一内部流水号切面
 */
@EnableAspectJAutoProxy
@Component
@Aspect
public class SndSeqAspect {

    private static final Logger LOG = LoggerFactory.getLogger(SndSeqAspect.class);

    //获取线程副本

    ThreadLocal<String> sndSeqThread = new ThreadLocal<>();


    @Pointcut("execution(* qf.*.*.controller..*.*(..)) || " +
              "execution(* qf.*.controller..*.*(..))")
    private void pointCutMethod() {
    }

    @Before("pointCutMethod()")
    public void BeforeMethod(JoinPoint joinPoint) {
        //获取请求报文头部元数据
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取请求对象
        HttpServletRequest request = requestAttributes.getRequest();

        StringBuffer sb = new StringBuffer();
        sb.append("url:").append(request.getRequestURI()).append("\t")
                .append("method").append(request.getMethod()).append("\t")
                .append("ip:").append(request.getRemoteAddr()).append("\t")
                .append("classMethod:").append(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()).append("\t")
                .append("args:").append(Arrays.toString(joinPoint.getArgs())).append("\t")
                .append("sndSeq:").append(request.getHeader("sndSeq"));

        LOG.info("请求生成内部流水号前处理开始:" + sb.toString());

        String sndSeq = "";
        if (request.getHeader("sndSeq") == null || "".equals(request.getHeader("sndSeq"))) {
            sndSeq = UUID.randomUUID().toString().replaceAll("-", "");
        } else {
            sndSeq = request.getHeader("sndSeq").toString();
        }

        MDC.put("sndSeq", sndSeq);
        //记录控制器执行前的时间毫秒数
        sndSeqThread.set(sndSeq);

        LOG.info("请求生成内部流水号处理完成。。");

    }

    /**
     * 最终处理
     */
    @After("pointCutMethod()")
    public void doFinaly() {
        LOG.info("请求生成内部流水号 最终处理，本次响应结束：内部流水号{}将移除", MDC.get("sndSeq"));
        MDC.remove("sndSeq");
    }

}
